using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BanZuiCloudControlAgent.Core.Mqtt.MessageCache;
using BanZuiCloudControlAgent.Core.Mqtt.Models;
using BanZuiCloudControlAgent.Core.Tasks.Queue;
using BanZuiCloudControlAgent.Utils.Common;
using BanZuiCloudControlAgent.Utils.Exceptions;
using BanZuiCloudControlAgent.Utils.Logging;

namespace BanZuiCloudControlAgent.Core.Mqtt.Sender
{
    /// <summary>
    /// MQTT消息发送器，负责发送各类MQTT消息
    /// </summary>
    public class MqttMessageSender
    {
        private readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
        private readonly MqttClientManager _clientManager;
        private readonly MqttTopics _mqttTopics;
        private readonly MqttMessageCache _messageCache;
        private bool _isInitialized = false;
        private bool _isProcessingCache = false;

        /// <summary>
        /// 获取MQTT客户端是否已连接
        /// </summary>
        public bool IsConnected => _clientManager?.IsConnected ?? false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="clientManager">MQTT客户端管理器</param>
        /// <param name="mqttTopics">MQTT主题</param>
        public MqttMessageSender(MqttClientManager clientManager, MqttTopics mqttTopics)
        {
            _clientManager = clientManager ?? throw new ArgumentNullException(nameof(clientManager));
            _mqttTopics = mqttTopics ?? throw new ArgumentNullException(nameof(mqttTopics));
            _messageCache = new MqttMessageCache(1000); // 最多缓存1000条消息
            
            // 订阅连接状态变更事件
            _clientManager.ConnectionStatusChanged += ClientManager_ConnectionStatusChanged;
            
            // 初始化消息缓存
            InitializeMessageCache();
        }
        
        /// <summary>
        /// 初始化消息缓存
        /// </summary>
        private async void InitializeMessageCache()
        {
            try
            {
                await _messageCache.InitializeAsync();
                _isInitialized = true;
                _logger.Info("MQTT消息缓存初始化完成");
                
                // 如果客户端已连接，则处理缓存的消息
                if (_clientManager.IsConnected)
                {
                    ProcessCachedMessagesAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"初始化MQTT消息缓存失败: {ex.Message}", ex);
            }
        }
        
        /// <summary>
        /// 处理连接状态变更事件
        /// </summary>
        private void ClientManager_ConnectionStatusChanged(object sender, MqttConnectionStatusChangedEventArgs e)
        {
            // 如果连接成功，且消息缓存已初始化，则处理缓存的消息
            if (e.IsConnected && _isInitialized)
            {
                ProcessCachedMessagesAsync();
            }
        }
        
        /// <summary>
        /// 处理缓存的消息
        /// </summary>
        private async void ProcessCachedMessagesAsync()
        {
            // 如果正在处理缓存，则直接返回
            if (_isProcessingCache)
            {
                return;
            }
            
            _isProcessingCache = true;
            
            try
            {
                _logger.Debug("开始处理缓存的消息");
                
                // 获取缓存的消息
                var messages = await _messageCache.GetPendingMessagesAsync(20); // 每次最多处理20条
                if (messages.Count == 0)
                {
                    _logger.Debug("没有缓存的消息需要发送");
                    _isProcessingCache = false;
                    return;
                }
                
                _logger.Info($"准备发送 {messages.Count} 条缓存的消息");
                
                foreach (var cachedMessage in messages)
                {
                    try
                    {
                        if (_clientManager.IsConnected)
                        {
                            // 发布消息
                            await _clientManager.PublishAsync(
                                cachedMessage.Topic,
                                cachedMessage.Payload,
                                cachedMessage.QosLevel,
                                cachedMessage.Retain);
                            
                            // 标记消息为已发送
                            await _messageCache.MarkMessageAsSentAsync(cachedMessage.MessageId);
                            
                            _logger.Debug($"已发送缓存的消息: {cachedMessage.MessageId}, 主题: {cachedMessage.Topic}");
                        }
                        else
                        {
                            // MQTT客户端未连接，停止处理
                            _logger.Warn("MQTT客户端未连接，停止处理缓存的消息");
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        // 发送失败，标记消息为发送失败
                        await _messageCache.MarkMessageAsFailedAsync(cachedMessage.MessageId);
                        _logger.Error($"发送缓存的消息失败: {cachedMessage.MessageId}, 错误: {ex.Message}", ex);
                    }
                }
                
                // 如果还有缓存的消息，继续处理
                if ((await _messageCache.GetPendingMessagesAsync(1)).Count > 0)
                {
                    ProcessCachedMessagesAsync();
                }
                else
                {
                    _isProcessingCache = false;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"处理缓存的消息失败: {ex.Message}", ex);
                _isProcessingCache = false;
            }
        }
        
        /// <summary>
        /// 发布消息，支持消息缓存和重发
        /// </summary>
        /// <param name="topic">主题</param>
        /// <param name="payload">消息内容</param>
        /// <param name="qosLevel">服务质量级别</param>
        /// <param name="retain">是否保留消息</param>
        /// <returns>发送结果</returns>
        private async Task<bool> PublishWithCacheAsync(string topic, string payload, int qosLevel = 0, bool retain = false)
        {
            try
            {
                // 尝试直接发送消息
                if (_clientManager.IsConnected)
                {
                    await _clientManager.PublishAsync(topic, payload, qosLevel, retain);
                    return true;
                }
                else
                {
                    // 客户端未连接，缓存消息
                    _logger.Debug($"MQTT客户端未连接，缓存消息: 主题={topic}");
                    
                    // 解析消息ID和类型，用于缓存
                    string messageId = null;
                    string messageType = null;
                    
                    try
                    {
                        var baseMessage = JsonHelper.Deserialize<BaseMessageModel>(payload);
                        if (baseMessage != null)
                        {
                            messageId = baseMessage.MessageId;
                            messageType = baseMessage.MessageType;
                        }
                    }
                    catch
                    {
                        // 解析失败，使用默认值
                        messageId = Guid.NewGuid().ToString();
                        messageType = "unknown";
                    }
                    
                    // 创建缓存消息
                    var cachedMessage = new CachedMessage
                    {
                        Id = Guid.NewGuid().ToString(),
                        MessageId = messageId,
                        MessageType = messageType,
                        Topic = topic,
                        Payload = payload,
                        QosLevel = qosLevel,
                        Retain = retain,
                        Timestamp = DateTime.Now,
                        RetryCount = 0
                    };
                    
                    // 添加到缓存
                    await AddCachedMessageAsync(cachedMessage);
                    
                    _logger.Debug($"消息已缓存: {messageId}, 主题: {topic}");
                    return true;
                }
            }
            catch (Exception ex)
            {
                _logger.Error($"发布消息失败: 主题={topic}, 错误={ex.Message}", ex);
                
                // 发送失败，尝试缓存消息
                if (_isInitialized)
                {
                    try
                    {
                        // 解析消息ID和类型，用于缓存
                        string messageId = null;
                        string messageType = null;
                        
                        try
                        {
                            var baseMessage = JsonHelper.Deserialize<BaseMessageModel>(payload);
                            if (baseMessage != null)
                            {
                                messageId = baseMessage.MessageId;
                                messageType = baseMessage.MessageType;
                            }
                        }
                        catch
                        {
                            // 解析失败，使用默认值
                            messageId = Guid.NewGuid().ToString();
                            messageType = "unknown";
                        }
                        
                        // 创建缓存消息
                        var cachedMessage = new CachedMessage
                        {
                            Id = Guid.NewGuid().ToString(),
                            MessageId = messageId,
                            MessageType = messageType,
                            Topic = topic,
                            Payload = payload,
                            QosLevel = qosLevel,
                            Retain = retain,
                            Timestamp = DateTime.Now,
                            RetryCount = 0
                        };
                        
                        // 添加到缓存
                        await AddCachedMessageAsync(cachedMessage);
                        
                        _logger.Debug($"消息发送失败已缓存: {messageId}, 主题: {topic}");
                    }
                    catch (Exception cacheEx)
                    {
                        _logger.Error($"缓存消息失败: 主题={topic}, 错误={cacheEx.Message}", cacheEx);
                    }
                }
                
                return false;
            }
        }
        
        /// <summary>
        /// 添加缓存消息
        /// </summary>
        /// <param name="cachedMessage">缓存消息</param>
        /// <returns>是否添加成功</returns>
        private async Task<bool> AddCachedMessageAsync(CachedMessage cachedMessage)
        {
            try
            {
                // 将缓存消息添加到消息缓存中
                return await _messageCache.AddMessageAsync(cachedMessage);
            }
            catch (Exception ex)
            {
                _logger.Error($"添加缓存消息失败: {ex.Message}", ex);
                return false;
            }
        }
        
        /// <summary>
        /// 发布消息对象，支持消息缓存和重发
        /// </summary>
        /// <param name="message">消息对象</param>
        /// <param name="topic">主题</param>
        /// <param name="qosLevel">服务质量级别</param>
        /// <param name="retain">是否保留消息</param>
        /// <returns>发送结果</returns>
        private async Task<bool> PublishMessageWithCacheAsync(BaseMessageModel message, string topic, int qosLevel = 0, bool retain = false)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            
            try
            {
                // 序列化消息
                string payload = JsonHelper.Serialize(message);
                
                // 发布消息
                return await PublishWithCacheAsync(topic, payload, qosLevel, retain);
            }
            catch (Exception ex)
            {
                _logger.Error($"发布消息对象失败: 消息ID={message.MessageId}, 错误={ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送状态上报消息
        /// </summary>
        /// <param name="isHeartbeat">是否为心跳消息</param>
        /// <param name="isFirstConnect">是否为首次连接</param>
        /// <param name="taskQueue">任务队列，用于获取任务状态</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendStatusReportAsync(bool isHeartbeat = true, bool isFirstConnect = false, TaskQueue taskQueue = null)
        {
            try
            {
                // 使用StatusReportModel的静态方法创建状态上报消息
                var statusReport = StatusReportModel.CreateStatusReport(
                    ConfigurationManager.UI.DeviceCode,
                    ConfigurationManager.UI.DeviceName,
                    isHeartbeat,
                    isFirstConnect,
                    taskQueue
                );

                // 发送消息
                bool result = await PublishMessageWithCacheAsync(statusReport, _mqttTopics.StatusReport, 0, false);
                if (result)
                {
                    _logger.Debug($"已发送状态上报消息，心跳: {isHeartbeat}, 首次连接: {isFirstConnect}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送状态上报消息失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送任务状态上报消息
        /// </summary>
        /// <param name="taskReport">任务状态上报消息</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendTaskReportAsync(TaskReportModel taskReport)
        {
            try
            {
                // 发送消息
                bool result = await PublishMessageWithCacheAsync(taskReport, _mqttTopics.TaskReport, 1, false);
                if (result)
                {
                    _logger.Debug($"已发送任务状态上报消息: {taskReport.MessageId}, 任务ID: {taskReport.GetPayload()?.TaskId}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送任务状态上报消息失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送错误上报消息
        /// </summary>
        /// <param name="errorType">错误类型</param>
        /// <param name="errorLevel">错误级别</param>
        /// <param name="errorCode">错误代码</param>
        /// <param name="errorMessage">错误消息</param>
        /// <param name="errorDetail">错误详情</param>
        /// <param name="taskId">任务ID</param>
        /// <param name="qqNumber">QQ号</param>
        /// <param name="context">上下文</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendErrorReportAsync(string errorType, int errorLevel, string errorCode, string errorMessage, 
            string errorDetail = null, string taskId = null, string qqNumber = null, object context = null)
        {
            try
            {
                // 创建错误上报消息
                var errorReport = new ErrorReportModel
                {
                    DeviceCode = ConfigurationManager.UI.DeviceCode,
                    Payload = new ErrorReportPayloadModel
                    {
                        ErrorType = errorType,
                        ErrorLevel = errorLevel,
                        ErrorCode = errorCode,
                        ErrorMessage = errorMessage,
                        ErrorDetail = errorDetail,
                        TaskId = taskId,
                        QQNumber = qqNumber,
                        Context = context != null ? new Dictionary<string, object> { { "context", context } } : new Dictionary<string, object>()
                    }
                };

                // 发送消息
                bool result = await PublishMessageWithCacheAsync(errorReport, _mqttTopics.ErrorReport, 1, false);
                if (result)
                {
                    _logger.Debug($"已发送错误上报消息，错误类型: {errorType}, 错误级别: {errorLevel}, 错误代码: {errorCode}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送错误上报消息失败，错误类型: {errorType}, 错误代码: {errorCode}, 错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送QQ在线列表上报消息
        /// </summary>
        /// <param name="onlineQQList">在线QQ列表</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendQQOnlineReportAsync(List<QQAccountInfoModel> onlineQQList)
        {
            try
            {
                if (onlineQQList == null)
                {
                    onlineQQList = new List<QQAccountInfoModel>();
                }

                // 创建QQ在线列表上报消息
                var qqOnlineReport = new QQOnlineReportModel
                {
                    DeviceCode = ConfigurationManager.UI.DeviceCode,
                    Payload = new QQOnlineReportPayloadModel
                    {
                        TotalCount = onlineQQList.Count,
                        OnlineQQList = onlineQQList
                    }
                };

                // 发送消息
                bool result = await PublishMessageWithCacheAsync(qqOnlineReport, _mqttTopics.QQOnlineReport, 1, false);
                if (result)
                {
                    _logger.Debug($"已发送QQ在线列表上报消息，在线QQ数量: {onlineQQList.Count}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送QQ在线列表上报消息失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送采集上报消息
        /// </summary>
        /// <param name="collectType">采集类型</param>
        /// <param name="qqNumber">QQ号</param>
        /// <param name="collectData">采集数据</param>
        /// <param name="collectTaskId">采集任务ID</param>
        /// <param name="batchNumber">批次号</param>
        /// <param name="totalBatches">总批次数</param>
        /// <param name="isLastBatch">是否为最后一批</param>
        /// <param name="totalCollected">总采集数量</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendCollectReportAsync(string collectType, string qqNumber, object collectData, 
            string collectTaskId = null, int batchNumber = 0, int totalBatches = 1, bool isLastBatch = true, int totalCollected = 0)
        {
            try
            {
                // 创建采集上报消息
                var collectReport = new CollectReportModel
                {
                    DeviceCode = ConfigurationManager.UI.DeviceCode,
                    Payload = new CollectReportPayloadModel
                    {
                        CollectType = collectType,
                        QQNumber = qqNumber,
                        CollectData = collectData != null ? new List<object> { collectData } : new List<object>(),
                        CollectCount = GetCollectCount(collectData),
                        CollectTaskId = collectTaskId,
                        BatchNumber = batchNumber,
                        TotalBatches = totalBatches,
                        IsLastBatch = isLastBatch,
                        TotalCollected = totalCollected
                    }
                };

                // 发送消息
                bool result = await PublishMessageWithCacheAsync(collectReport, _mqttTopics.CollectReport, 1, false);
                if (result)
                {
                    _logger.Debug($"已发送采集上报消息，采集类型: {collectType}, QQ号: {qqNumber}, 批次: {batchNumber}/{totalBatches}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送采集上报消息失败，采集类型: {collectType}, QQ号: {qqNumber}, 错误: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 发送断开连接消息
        /// </summary>
        /// <param name="reason">断开原因</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendDisconnectMessageAsync(string reason = "normal_disconnect")
        {
            try
            {
                // 创建断开连接消息
                var disconnectModel = new DisconnectModel
                {
                    DeviceCode = ConfigurationManager.UI.DeviceCode,
                    Payload = new DisconnectPayloadModel
                    {
                        Reason = reason,
                        LastStatus = new Dictionary<string, object>
                        {
                            { "memoryUsage", SystemInfo.GetMemoryUsage().UsagePercentage },
                            { "cpuUsage", SystemInfo.GetCpuUsage() }
                        }
                    }
                };

                // 发送消息
                // 使用状态上报主题发送断开连接消息（根据MqttTopics.GetPublishTopicByMessageType的实现）
                bool result = await PublishMessageWithCacheAsync(disconnectModel, _mqttTopics.StatusReport, 1, false);
                if (result)
                {
                    _logger.Debug($"已发送断开连接消息，原因: {reason}");
                }
                return result;
            }
            catch (Exception ex)
            {
                _logger.Error($"发送断开连接消息失败: {ex.Message}", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取采集数量
        /// </summary>
        /// <param name="collectData">采集数据</param>
        /// <returns>采集数量</returns>
        private int GetCollectCount(object collectData)
        {
            if (collectData == null)
            {
                return 0;
            }

            if (collectData is ICollection<object> collection)
            {
                return collection.Count;
            }

            if (collectData is Array array)
            {
                return array.Length;
            }

            if (collectData is IEnumerable<object>)
            {
                return 1; // 至少有一个元素
            }

            return 1; // 默认为1
        }
    }
} 